package com.wsh.crawler.service.impl.parser;


import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
import com.wsh.crawler.constant.LanguageEnum;
import com.wsh.crawler.constant.NewsSourceEnum;
import com.wsh.crawler.entity.News;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

public class FlashScoreParser extends AbstractNewsParser {

    private final static Logger LOGGER = LoggerFactory.getLogger(FlashScoreParser.class);

    // FlashScore OSS的域名（如果变动需变更）
    private final static String OSS_DOMAIN = "https://livesport-ott-images.ssl.cdn.cra.cz";

    public FlashScoreParser() {
        super(NewsSourceEnum.FLASHSCORE.getName());
    }

    @Override
    public List<String> parseArticleLinks(Document doc) {
        List<String> links = new ArrayList<>();

        try {
            // 核心改进：只从新闻区域获取文章链接
            Element newsSection = doc.selectFirst("#fsNews.fsNews");
            if (newsSection == null) {
                LOGGER.warn("【FlashScore解析】未找到新闻区域 #fsNews");
                // 降级处理：使用备用选择器
                return parseArticleLinksFallback(doc);
            }

            LOGGER.info("【FlashScore解析】找到新闻区域，开始解析文章链接");

            // 方法1：在新闻区域内查找带有特定data-testid的文章链接
            Elements articleLinks = newsSection.select("a[data-testid='wcl-newsArticlePreview']");
            LOGGER.info("【FlashScore解析】方法1找到{}个wcl-newsArticlePreview链接", articleLinks.size());

            for (Element article : articleLinks) {
                String href = article.attr("href");
                if (!href.isEmpty()) {
                    String fullUrl = makeAbsoluteUrl(href);
                    if (isValidNewsUrl(fullUrl)) {
                        links.add(fullUrl);
                    }
                }
            }

            // 方法2：在新闻区域内查找article元素内的链接
            Elements articles = newsSection.select("article[data-testid='fp-newsArticle']");
            LOGGER.info("【FlashScore解析】方法2找到{}个fp-newsArticle元素", articles.size());

            for (Element article : articles) {
                Elements aElements = article.select("a[href]");
                for (Element a : aElements) {
                    String href = a.attr("href");
                    if (!href.isEmpty()) {
                        String fullUrl = makeAbsoluteUrl(href);
                        if (isValidNewsUrl(fullUrl)) {
                            links.add(fullUrl);
                        }
                    }
                }
            }

            // 方法3：查找新闻区域内其他可能的新闻链接
            Elements otherLinks = newsSection.select("a[href*='/news/'], a[href*='article']");
            LOGGER.info("【FlashScore解析】方法3找到{}个其他新闻链接", otherLinks.size());

            for (Element link : otherLinks) {
                String href = link.attr("href");
                if (!href.isEmpty()) {
                    String fullUrl = makeAbsoluteUrl(href);
                    if (isValidNewsUrl(fullUrl)) {
                        links.add(fullUrl);
                    }
                }
            }

        } catch (Exception e) {
            LOGGER.error("【FlashScore解析】解析文章链接异常", e);
            return parseArticleLinksFallback(doc);
        }

        // 去重并返回
        List<String> distinctLinks = links.stream().distinct().collect(Collectors.toList());
        LOGGER.info("【FlashScore解析】总共解析到{}个有效文章链接（去重后）", distinctLinks.size());

        return distinctLinks;
    }

    /**
     * 降级处理：当主要方法失败时的备用解析
     */
    private List<String> parseArticleLinksFallback(Document doc) {
        LOGGER.info("【FlashScore解析】使用备用方法解析文章链接");
        List<String> links = new ArrayList<>();

        // 使用更宽泛但安全的选择器
        Elements articleLinks = doc.select("a[data-testid='wcl-newsArticlePreview']");

        for (Element article : articleLinks) {
            String href = article.attr("href");
            if (!href.isEmpty()) {
                String fullUrl = makeAbsoluteUrl(href);
                if (isValidNewsUrl(fullUrl)) {
                    links.add(fullUrl);
                }
            }
        }

        return links.stream().distinct().limit(20).collect(Collectors.toList());
    }

    /**
     * 将相对URL转换为绝对URL
     */
    private String makeAbsoluteUrl(String href) {
        if (href.startsWith("http")) {
            return href;
        }
        if (href.startsWith("/")) {
            return "https://www.flashscore.com" + href;
        }
        return "https://www.flashscore.com/" + href;
    }

    /**
     * 验证是否为有效的新闻URL
     */
    private boolean isValidNewsUrl(String url) {
        if (url == null || url.trim().isEmpty()) {
            return false;
        }

        String lowerUrl = url.toLowerCase();

        // 必须是FlashScore的URL
        if (!lowerUrl.contains("flashscore.com")) {
            return false;
        }

        // 必须包含新闻相关路径
        if (!lowerUrl.contains("/news/") && !lowerUrl.contains("article")) {
            return false;
        }

        // 排除明显的非新闻内容
        return !lowerUrl.contains("gambling") &&
                !lowerUrl.contains("betting") &&
                !lowerUrl.contains("casino") &&
                !lowerUrl.contains("poker") &&
                !lowerUrl.contains("livetable") &&
                !lowerUrl.contains("javascript:") &&
                !lowerUrl.contains("#") &&
                !lowerUrl.endsWith(".css") &&
                !lowerUrl.endsWith(".js") &&
                !lowerUrl.endsWith(".png") &&
                !lowerUrl.endsWith(".jpg");
    }

    @Override
    public News parseArticle(Document doc, String url) {
        LOGGER.info("【FlashScore解析】正在解析{}的文章", url);
        News article = new News();
        article.setSource(NewsSourceEnum.FLASHSCORE.getName());
        article.setOriginalUrl(url);
        article.setCrawlTime(new Date());

        // 解析标题
        Element titleElement = doc.selectFirst("h1");
        if (titleElement != null) {
            article.setTitle(titleElement.text().trim());
        }

        if (article.getTitle() == null || article.getTitle().isEmpty()) {
            titleElement = doc.selectFirst(".wcl-headline_buFBe, [data-testid*='heading']");
            if (titleElement != null) {
                article.setTitle(titleElement.text().trim());
            }
        }

        // 修正选择器：加上正确的FlashScore内容区域class
        Element contentElement = doc.selectFirst(
                ".fsNewsArticle__content, " +
                        ".article-body, " +
                        ".article-content, " +
                        ".wcl-article-body, " +
                        "[data-testid='article-body'], " +
                        "[data-testid='article-content'], " +
                        ".content-body"
        );

        if (contentElement != null) {
            LOGGER.info("【FlashScore解析】找到内容区域：{}", contentElement.className());
            String content = contentElement.text().trim();
            article.setContent(content);
            LOGGER.info("【FlashScore解析】内容长度：{}", content.length());
        } else {
            LOGGER.warn("【FlashScore解析】未找到内容区域，尝试备用方法");

            // 备用方法：从文章容器中提取内容
            Elements contentElements = doc.select("article[data-testid='fp-newsArticle'] p, " +
                    ".wcl-wrapper_wAjqW p, " +
                    "#fsNews p");

            StringBuilder contentBuilder = new StringBuilder();
            for (Element element : contentElements) {
                String text = element.text().trim();

                // 过滤掉导航、广告等无关内容
                String className = element.className().toLowerCase();
                if (className.contains("nav") || className.contains("menu") ||
                        className.contains("ad") || className.contains("footer")) {
                    continue;
                }

                if (text.length() > 20) { // 过滤太短的文本
                    contentBuilder.append(text).append("\n\n");
                }
            }

            if (contentBuilder.length() > 0) {
                article.setContent(contentBuilder.toString().trim());
                LOGGER.info("【FlashScore解析】通过备用方法获取内容，长度：{}", article.getContent().length());
            }
        }

        // 提取图片和视频
        article.setImageUrls(extractImageUrls(doc));
        article.setVideoUrls(extractVideoUrls(doc));
        article.setLanguage(LanguageEnum.EN.getValue());

        // 提取封面图片
        String coverUrl = extractCoverImage(doc, article.getImageUrls());
        article.setOriginalCoverUrl(coverUrl);
        article.setCoverUrl(coverUrl);

        return article;
    }

    /**
     * 提取封面图片
     * @param doc 文档对象
     * @param otherImageUrls 其他图片
     * @return 封面图片URL
     */
    @Override
    public String extractCoverImage(Document doc, List<String> otherImageUrls) {
        LOGGER.info("【FlashScore解析】开始提取封面图片");

        // 1. 优先从meta标签获取
        String coverUrl = extractCoverFromMeta(doc);
        if (isValidImageUrl(coverUrl)) {
            LOGGER.info("【FlashScore解析】从meta标签获取封面：{}", coverUrl);
            return coverUrl;
        }

        // 2. 从特定的封面图片选择器获取
        if (CollectionUtils.isNotEmpty(otherImageUrls)) {
            for (String imageUrl : otherImageUrls) {
                // 是否业务系统OSS图片，是的话随便拿一条返回作为封面
                if (imageUrl.contains(OSS_DOMAIN)) {
                    LOGGER.info("【FlashScore解析】从图片内容选一张作为封面：{}", imageUrl);
                    return imageUrl;
                }
            }
        }

        LOGGER.warn("【FlashScore解析】未找到合适的封面图片");
        return null;
    }

    /**
     * 从meta标签提取封面图片
     */
    private String extractCoverFromMeta(Document doc) {
        // Open Graph标签
        Element ogImage = doc.selectFirst("meta[property=og:image]");
        if (ogImage != null) {
            String content = ogImage.attr("content");
            if (!content.isEmpty()) {
                return content;
            }
        }

        // Twitter卡片标签
        Element twitterImage = doc.selectFirst("meta[name=twitter:image], meta[property=twitter:image]");
        if (twitterImage != null) {
            String content = twitterImage.attr("content");
            if (!content.isEmpty()) {
                return content;
            }
        }

        // 其他可能的meta标签
        Element metaImage = doc.selectFirst("meta[name=image], meta[property=image]");
        if (metaImage != null) {
            String content = metaImage.attr("content");
            if (!content.isEmpty()) {
                return content;
            }
        }

        return null;
    }

    /**
     * 验证是否为有效的图片URL
     */
    private boolean isValidImageUrl(String url) {
        if (url == null || url.trim().isEmpty()) {
            return false;
        }

        String lowerUrl = url.toLowerCase();
        return lowerUrl.contains("jpg") || lowerUrl.contains("jpeg") ||
                lowerUrl.contains("png") || lowerUrl.contains("gif") ||
                lowerUrl.contains("webp") || lowerUrl.contains("svg") ||
                lowerUrl.startsWith("data:image/");
    }

    @Override
    protected List<String> extractImageUrls(Document doc) {
        List<String> imageUrls = new ArrayList<>();

        // 从文章内容中提取图片
        doc.select("img[src]").forEach(img -> {
            String src = img.attr("abs:src");
            if (!src.isEmpty() && !src.contains("placeholder")) {
                imageUrls.add(src);
            }
        });

        // 特别处理FlashScore的picture标签内的图片
        doc.select("picture img[src]").forEach(img -> {
            String src = img.attr("abs:src");
            if (!src.isEmpty() && !src.contains("placeholder")) {
                imageUrls.add(src);
            }
        });

        return imageUrls.stream().distinct().collect(Collectors.toList());
    }

    @Override
    protected List<String> extractVideoUrls(Document doc) {
        List<String> videoUrls = new ArrayList<>();

        // 查找video标签
        doc.select("video source").forEach(video -> {
            String url = video.attr("abs:src");
            if (!url.isEmpty()) {
                videoUrls.add(url);
            }
        });

        // 查找iframe嵌入的视频
        doc.select("iframe[src*=youtube], iframe[src*=vimeo], iframe[src*=dailymotion]").forEach(iframe -> {
            String url = iframe.attr("abs:src");
            if (!url.isEmpty()) {
                videoUrls.add(url);
            }
        });

        return videoUrls;
    }
}